﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
using Gecko;
using Gecko.DOM;
using System.IO;
using System.Text;

namespace WebBrowserGecko
{
    public partial class Form1 : Form
    {
        public const string urlLoginPage = "https://khstage.etaxi.ua";

        private GeckoWebBrowser _browser;
        private bool _waitChooseDriver = false;
        private bool _waitAssyncOper = false;
        //private static AutoResetEvent eventDocumentCompleted = new AutoResetEvent(false);
        //private Object thisLock = new Object();
        //bool lockWasTaken = false;
        //Object temp = new Object();

        delegate void SomeDelegate();

        public Form1()
        {
            InitializeComponent();

            Gecko.Xpcom.Initialize("d:\\Projects\\Test C#\\WebBrowserGecko\\WebBrowserGecko\\xulrunner");
            _browser = new GeckoWebBrowser();
            _browser.Dock = DockStyle.Fill;
            pnlBrowser.Controls.Add(_browser);
            GeckoPreferences.User["security.warn_viewing_mixed"] = false;
            _browser.DocumentCompleted += browserDocumentCompleted;
            _browser.Navigate("https://khstage.etaxi.ua");
        }

        private void browserDocumentCompleted(object sender, EventArgs e)
        {
            if (_waitAssyncOper)
            {
                return;
            }

            if (IsLoginPage())
            {
                DoLogin();
            }
            else if (IsOrdersPage())
            {
                OpenStatisticsPage();
            }
            else if (IsStatisticsPage())
            {
                if (!IsDriversTab())
                {
                    OpenDriversTab();
                }
                else
                {
                    if (!_waitChooseDriver)
                    {
                        ChooseDriver();
                    }
                    else
                    {
                        if (ExistComboListInner())
                        {
                            SelectDriverItem();
                        }
                    }
                }

            }
        }

        private GeckoElement GetGeckoElementById(string id)
        {
            return (_browser.Document.GetElementById(id));
        }

        //private GeckoElement GetGeckoElementById(GeckoElement element, string id)
        //{
        //    foreach (GeckoHtmlElement item in element.GetElements(id))
        //    {
        //        item.NodeValue = "QQQ";
        //    }
        //    return null;
        //}

        private GeckoElement GetGeckoElementByName(string name)
        {
            return (_browser.Document.GetElementsByName(name)[0]);
        }

        private GeckoElement GetGeckoElementByAttribute(string elementName, string attributeName, string attributeValue)
        {
            GeckoElementCollection elements = _browser.Document.GetElementsByTagName(elementName);
            foreach (GeckoElement element in elements)
            {
                if (element.GetAttribute(attributeName) == attributeValue)
                {
                    return element;
                }
            }
            return null;
        }

        private Boolean IsLoginPage()
        {
            return (GetGeckoElementById("loginForm") != null);
        }

        private Boolean IsStatisticsPage()
        {
            GeckoElement element = GetGeckoElementById("statisticsTopElement");
            string attribute = element.GetAttribute("class");
            if (attribute != null)
            {
                return (attribute.Equals("active"));
            }
            else{
                return false;
            }
        }

        private Boolean IsOrdersPage()
        {
            GeckoElement element = GetGeckoElementById("orderBrowseTopElement");
            string attribute = element.GetAttribute("class");
            if (attribute != null)
            {
                return (attribute.Equals("active"));
            }
            else
            {
                return false;
            }
        }

        private Boolean IsDriversTab()
        {
            if (IsStatisticsPage())
            {
                GeckoElement element = GetGeckoElementByAttribute("div", "ext:tree-node-id", "drivers");
                string attribute = element.GetAttribute("class");
                if (attribute != null)
                {
                    return (attribute.Contains("x-tree-selected"));
                }
            }
            return false;
        }

        private Boolean ExistComboListInner()
        {
            if (IsStatisticsPage())
            {
                GeckoElement element = GetGeckoElementByAttribute("div", "class", "x-combo-list-inner");
                return (element != null);
            }
            return false;
        }

        private void OpenLoginPage()
        {
            _browser.Navigate(urlLoginPage);
        }

        private void OpenStatisticsPage()
        {
            GeckoElement element = GetGeckoElementById("statisticsTopElement");
            GeckoAnchorElement anchor = (GeckoAnchorElement)element.GetElementsByTagName("a")[0];
            anchor.Click();
        }

        private void OpenDriversTab()
        {
            GeckoElement element = GetGeckoElementByAttribute("div", "ext:tree-node-id", "drivers");
            GeckoAnchorElement anchor = (GeckoAnchorElement)element.GetElementsByTagName("a")[0];
            anchor.Click();
        }

        private void ChooseDriver()
        {
            GeckoInputElement input = (GeckoInputElement)GetGeckoElementByName("concreteCategorySearchCombo");
            input.Value = "04";            

            //GeckoElement element = GetGeckoElementByAttribute("button", "class", "x-btn-text refresh");
            //GeckoButtonElement button = (GeckoButtonElement)element;
            //button.Click();

            GeckoElement element = GetGeckoElementByAttribute("img", "src", "rc/js/ext-js/resources/images/default/s.gif");
            GeckoImageElement image = (GeckoImageElement)element;
            image.Click();

            _waitChooseDriver = true;            
        }

        private void SelectDriverItem()
        {
            GeckoElement element2 = GetGeckoElementByAttribute("div", "class", "x-combo-list-item  x-combo-selected");
            GeckoImageElement image2 = (GeckoImageElement)element2;
            image2.Click();

            _waitChooseDriver = true;
        }

        private void DoLogin()
        {
            GeckoInputElement input;
            input = (GeckoInputElement)GetGeckoElementByName("dsAccountName");
            input.Value = "demokh";
            input = (GeckoInputElement)GetGeckoElementByName("login");
            input.Value = "manager";
            input = (GeckoInputElement)GetGeckoElementByName("password");
            input.Value = "manager";
            input = (GeckoInputElement)GetGeckoElementById("submit");
            input.click();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //ChooseDriver();
            SelectDriver();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            //SomeDelegate sd = Login;
            //IAsyncResult asyncRes = sd.BeginInvoke(10, null, null);
            //sd.EndInvoke(asyncRes);	        
        }

        private GeckoDivElement GetComboListInner()
        {
            GeckoElementCollection elements = _browser.Document.GetElementsByTagName("div");
            foreach (GeckoElement element in elements)
            {
                GeckoDivElement div = (GeckoDivElement)element;
                if (div.ClassName == "x-combo-list-inner")
                {
                    return div;
                }
            }
            return null;
        }

        private GeckoDivElement GetComboListItem(GeckoDivElement combo, string value)
        {
            GeckoElementCollection elements = combo.GetElementsByTagName("div");
            foreach (GeckoElement element in elements)
            {
                if (element.TextContent == value)
                {
                    return (GeckoDivElement)element;
                }
            }
            return null;
        }

        private bool IsLoadingComboListInner(GeckoDivElement combo)
        {
            GeckoElementCollection elements = combo.GetElementsByTagName("div");
            foreach (GeckoElement element in elements)
            {
                GeckoDivElement div = (GeckoDivElement)element;
                if (div.ClassName == "loading-indicator")
                {
                    return true;
                }
            }
            return false;
        }

        private GeckoButtonElement GetRefreshButton()
        {
            GeckoElementCollection elements = _browser.Document.GetElementsByTagName("button");
            foreach (GeckoElement element in elements)
            {
                GeckoButtonElement button = (GeckoButtonElement)element;
                if (button.ClassName.Equals("x-btn-text refresh"))
                {
                    return button;
                }
            }
            return null;
        }

        private void FillDriverIdInDropdownList(string driverId)
        {
            GeckoInputElement input = (GeckoInputElement)GetGeckoElementById("concreteCategorySearchCombo");
            input.Value = driverId;
        }

        private void OpenDropdownListOfDrivers()
        {
            GeckoImageElement image = (GeckoImageElement)GetGeckoElementByAttribute("img", "src", "rc/js/ext-js/resources/images/default/s.gif");
            image.Click();
        }

        private void WaitLoadingDropdownList()
        {
            System.Timers.Timer timer;
            bool timer_overflov = false;

            timer = new System.Timers.Timer();
            timer.AutoReset = false;
            timer.Elapsed += delegate { timer_overflov = true; };

            timer.Interval = 5000;
            timer.Enabled = true;
            // Нужно вынести работу со страницей статистики вынести в отдельный класс.
            // Поможет избавиться от постоянных поисков элементов.
            GeckoDivElement combo = GetComboListInner();
            while ((timer_overflov == false) & (IsLoadingComboListInner(combo) == true))
            { 
                Application.DoEvents();
                Thread.Sleep(1000);
            }
            if (timer_overflov == true)
            {
                throw new Exception("Вышло время ожидания загрузки выпадающего списка.");
            }
        }

        private void SelectItemFromDropdownList(string driverId)
        {
            GeckoDivElement combo = GetComboListInner();
            GeckoDivElement item = GetComboListItem(combo, driverId);
            if (item != null) 
            {
                item.Click();
                GeckoButtonElement button = GetRefreshButton();
                button.Click();
            }
            else
            {
                throw new Exception(string.Format("В выпадающем списке не найден элемент со значением \"{0}\".", driverId));
            }
        }

        private void SelectDriver()
        {
            FillDriverIdInDropdownList("04");
            OpenDropdownListOfDrivers();
            WaitLoadingDropdownList();
            SelectItemFromDropdownList("04");
        }
    }
}
